package rozpoznawanieCyfr;

import generatorWektorow.GeneratorWektorow;
import generatorWektorow.ParserWektorow;
import gui.GuiLogger;

import java.io.IOException;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Appender;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.varia.NullAppender;

import typydanych.Wektor;
import KNN.IMetryka;
import KNN.KNN;

public class RozpoznawanieCyfr {

	private static Logger LOG = Logger.getLogger(RozpoznawanieCyfr.class);
	public boolean krzyweZamkniete = true;
	public boolean luki = true;
	public boolean ciezkoscSrodka = true;
	public boolean gornaStrefa = true;
	public int liczbaSasiadow = 6;
	public String obrazyUczace = "train-images.idx3-ubyte";
	public String etykietyUczace = "train-labels.idx1-ubyte";
	public String obrazyTestujace = "t10k-images.idx3-ubyte";
	public String etykietyTestujace = "t10k-labels.idx1-ubyte";
	public String wektoryUczace = "wektoryUczace.knn";
	public String wektoryTestujace = "wektoryTestujace.knn";

	public void wygenerujWektory(GuiLogger guiLogger) throws IOException {

		long czasStartu = new Date().getTime();

		GeneratorWektorow generatorUczacy = wczytajZbior(obrazyUczace, etykietyUczace, guiLogger);
		LOG.info("wczytano zbior uczacy");
		zapiszWektory(wektoryUczace, generatorUczacy.getListaWektorow());
		LOG.info("zapisano zbior uczacy");
		GeneratorWektorow generatorTestujacy = wczytajZbior(obrazyTestujace, etykietyTestujace, guiLogger);
		LOG.info("wczytano zbior testujacy");
		zapiszWektory(wektoryTestujace, generatorTestujacy.getListaWektorow());
		LOG.info("zapisano zbior testujacy");

		long czasZakonczenia = new Date().getTime();
		LOG.info("Czas trwania operacji [ms]: " + (czasZakonczenia - czasStartu));

	}

	public double rozpoznawaj(IMetryka metryka,GuiLogger logger, boolean normalizuj) throws Exception {
		long czasStartu = new Date().getTime();

		List<Wektor> listaWektorowUczacych = wczytajWektory(wektoryUczace);
		LOG.info("wczytano wektory uczace");
		List<Wektor> listaWektorowTestujacych = wczytajWektory(wektoryTestujace);
		LOG.info("wczytano wektory testujace");
		double skutecznoscKlasyfikacji = klasyfikuj(listaWektorowUczacych, listaWektorowTestujacych, metryka,logger, normalizuj);
		LOG.info("skutecznosc klasyfikacji = " + skutecznoscKlasyfikacji);

		long czasZakonczenia = new Date().getTime();
		LOG.info("Czas trwania operacji [ms]: " + (czasZakonczenia - czasStartu));
		
		return skutecznoscKlasyfikacji;
	}

	public GeneratorWektorow wczytajZbior(String sciezkaObrazkow, String sciezkaEtykiet, GuiLogger guiLogger) throws IOException {
		GeneratorWektorow wektoryUczace = new GeneratorWektorow();
		wektoryUczace.setLogger(guiLogger);
		wektoryUczace.generujWektory(sciezkaObrazkow, sciezkaEtykiet, krzyweZamkniete, luki, ciezkoscSrodka, gornaStrefa);
		return wektoryUczace;
	}

	public static void zapiszWektory(String sciezka, List<Wektor> listaWektorow) throws IOException {
		ParserWektorow parser = new ParserWektorow();
		parser.zapiszWektory(sciezka, listaWektorow);
	}

	public static List<Wektor> wczytajWektory(String sciezka) throws IOException {
		ParserWektorow parser = new ParserWektorow();
		return parser.wczytajWektory(sciezka);
	}

	/**
	 * 
	 * @param wektoryUczace
	 * @param wektoryTestujace
	 * @return procentowa poprawnosc klasyfikacji
	 * @throws Exception
	 */
	public double klasyfikuj(List<Wektor> wektoryUczace, List<Wektor> wektoryTestujace, IMetryka metryka,GuiLogger logger, boolean normalizuj) throws Exception {
		KNN knn = new KNN();
		knn.setMetryka(metryka);
		knn.setLogger(logger);
		knn.setLiczbaSasiadow(liczbaSasiadow);
		knn.setZbiorUczacy(wektoryUczace);
		knn.setZbiorTestowy(wektoryTestujace);
		knn.setNormalizuj(normalizuj);
		knn.klasyfikuj();
		return knn.getSkutecznoscKlasyfikacji();
	}

	public RozpoznawanieCyfr() {
		LOG.addAppender(new NullAppender());
	}

	public RozpoznawanieCyfr(Appender loggerAppender) {
		LOG.addAppender(loggerAppender);
	}
	
	public void podlaczConsoleAppender(){
		LOG.addAppender(new ConsoleAppender(new PatternLayout()));
	}

	public boolean isKrzyweZamkniete() {
		return krzyweZamkniete;
	}

	public void setKrzyweZamkniete(boolean krzyweZamkniete) {
		this.krzyweZamkniete = krzyweZamkniete;
	}

	public boolean isLuki() {
		return luki;
	}

	public void setLuki(boolean luki) {
		this.luki = luki;
	}

	public boolean isCiezkoscSrodka() {
		return ciezkoscSrodka;
	}

	public void setCiezkoscSrodka(boolean ciezkoscSrodka) {
		this.ciezkoscSrodka = ciezkoscSrodka;
	}

	public boolean isGornaStrefa() {
		return gornaStrefa;
	}

	public void setGornaStrefa(boolean gornaStrefa) {
		this.gornaStrefa = gornaStrefa;
	}

	public int getLiczbaSasiadow() {
		return liczbaSasiadow;
	}

	public void setLiczbaSasiadow(int liczbaSasiadow) {
		this.liczbaSasiadow = liczbaSasiadow;
	}

	public String getObrazyUczace() {
		return obrazyUczace;
	}

	public void setObrazyUczace(String obrazyUczace) {
		this.obrazyUczace = obrazyUczace;
	}

	public String getEtykietyUczace() {
		return etykietyUczace;
	}

	public void setEtykietyUczace(String etykietyUczace) {
		this.etykietyUczace = etykietyUczace;
	}

	public String getObrazyTestujace() {
		return obrazyTestujace;
	}

	public void setObrazyTestujace(String obrazyTestujace) {
		this.obrazyTestujace = obrazyTestujace;
	}

	public String getEtykietyTestujace() {
		return etykietyTestujace;
	}

	public void setEtykietyTestujace(String etykietyTestujace) {
		this.etykietyTestujace = etykietyTestujace;
	}

	public String getWektoryUczace() {
		return wektoryUczace;
	}

	public void setWektoryUczace(String wektoryUczace) {
		this.wektoryUczace = wektoryUczace;
	}

	public String getWektoryTestujace() {
		return wektoryTestujace;
	}

	public void setWektoryTestujace(String wektoryTestujace) {
		this.wektoryTestujace = wektoryTestujace;
	}

}
